package xdu.lz.stage2_design_pattern.chapter5_reader_writer_pattern;

public class ReadWriteLock {
    //当前 进行读操作的 线程个数
    private int isReading = 0;
    //当前 想读但是读不了的线程数，放到waitSet队列中
    private int waitReading = 0;
    //当前 正在写的线程个数 <=1
    private int isWriting = 0;
    //当前 正在等待写的线程个数
    private int waitWriting = 0;

    //是否让读权限更高
    private boolean preferWriter = true;

    public ReadWriteLock() {
        this(true);
    }

    public ReadWriteLock(boolean preferWriter) {
        this.preferWriter = preferWriter;
    }

    //尝试获得读锁
    public synchronized void readLock() throws InterruptedException {
        //1正在等待读的线程数++
        this.waitReading++;
        try {
            //2如果有人在写，则不能读，进入waitSet
            //修改后：如果有人在写或者   有人等待写并且跟偏向写，那么让写先执行，读等
            while (isWriting > 0 || (preferWriter && waitWriting >0)) {
                this.wait();
            }
            //3while不成立代表没有任何人在写，所以可以进行读，读的线程数+1
            this.isReading++;
        } finally {
            //4等待读的线程数 --
            this.waitReading--;
        }
    }

    //读完后释放读锁
    public synchronized void readUnLock() {
        this.isReading--;
        //通知在waitSet中的线程
        this.notifyAll();
        System.out.println("通知了");
    }

    //尝试获得写锁
    public synchronized void writeLock() throws InterruptedException{
        this.waitWriting++;
        try{
            //如果有人正在读或者有人正在写，则等待
            while (this.isReading >0 || this.isWriting >0){
                this.wait();
            }
            //否则可以写,最多是1个正在写
            this.isWriting++;
        }finally {
            this.waitWriting--;
        }
    }
    //写完后释放锁
    public synchronized void writeUnLock(){
        this.isWriting--;
        this.notifyAll();
        System.out.println("通知了");
    }
}
